home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Utilities / uupc 3.1 / Mac specific / Unix lib / sio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-05  |  12.3 KB  |  651 lines  |  [TEXT/KAHL]

  1. /*            sio.c
  2.  
  3.  
  4.                 Serial I/O for rz/sz
  5.  
  6.  
  7.                 Copyright (c) 1986 Stuart Lynne
  8.  
  9.                 June 1986
  10.  
  11.                 Modified for Think C
  12.                 
  13.                 Sak Wathanasin 1989
  14.  
  15.             Portions Copyright © David Platt, 1992, 1991.  All Rights Reserved
  16.             Worldwide.
  17.  
  18. */
  19. #include "sio.h"
  20.  
  21. #include <stdio.h>
  22. #ifndef  THINK_C
  23. #include <pb.h>
  24.  
  25. #include <osutil.h>
  26.  
  27. /* #include <max/macglobals.h> */
  28. #include <max/debug.h>
  29. #include <max/asc.h>
  30. #else   THINK_C
  31. # include "dcp.h"
  32. #endif   THINK_C
  33.  
  34. #ifndef FALSE
  35. # define FALSE 0
  36. #endif FALSE
  37. #ifndef TRUE
  38. # define TRUE 1
  39. #endif TRUE
  40.  
  41. #ifdef Upgrade
  42. static int g_setting;
  43. #endif Upgrade
  44.  
  45. struct SIOPort curPort={0};
  46.  
  47. #ifdef DOASYNC
  48.  
  49. static struct async_write *asyncout;
  50. static int async_head, async_tail, async_pending;
  51. static int allowInterrupts = FALSE;
  52. static int interruptOccurred = FALSE;
  53. static int sleepLimit = 3;
  54. extern SysEnvRec SysEnv;
  55.  
  56. #endif
  57.  
  58. #define baud38400 1
  59.  
  60. #include "sio.proto.h"
  61. static unsigned int getspeed(int code);
  62. static unsigned getbaud(char *code);
  63.  
  64. struct {
  65.     unsigned int baudr;
  66.     int speedcode;
  67. } speeds[] = {
  68.     300,    baud300,
  69.     600,    baud600,
  70.     1200,    baud1200,
  71.     2400,    baud2400,
  72.     4800,    baud4800,
  73.     9600,    baud9600,
  74.     19200,    baud19200,
  75.     38400,     baud38400,
  76.     57600,     baud57600,
  77.     0,
  78. };
  79.  
  80. static char otherIn[] = "\p.?In";
  81. static char otherOut[] = "\p.?Out";
  82.  
  83. ConnectionHandler serialHandler = {
  84.     SIOInit,
  85.     SIOInBuffer,
  86.     SIOOutBuffer,
  87.     SIOSpeed,
  88.     SIOHandshake,
  89.     SIOSetting,
  90.     SIOClose,
  91.     SIOSetFlowCtl,
  92.      SIOAllowInterrupts,
  93.     SIOInterrupt,
  94.     SIOPurge,
  95.     SIOPutchar,
  96.     SIOWrite,
  97.     SIOAvail,
  98.     SIOWStr,
  99.     SIORead,
  100.     SIOIdle,
  101.     SIOEvent,
  102.     SIOBreak,
  103.     SIOSetParity
  104. };
  105.  
  106.  
  107. static unsigned int
  108. getspeed(int code)
  109. {
  110.     register n;
  111.  
  112.     for (n=0; speeds[n].baudr; ++n)
  113.         if (speeds[n].speedcode == code)
  114.             return speeds[n].baudr;
  115.     return -1;
  116. }
  117.  
  118.  
  119. static unsigned
  120. getbaud(char *code) {
  121.     register n;
  122.     register long int Baudrate;
  123.     
  124.     Baudrate = atol(code);
  125.     
  126.     for(n=0 ; speeds[n].baudr ; ++n)
  127.         if(speeds[n].baudr == Baudrate)
  128.             return(speeds[n].speedcode);
  129.     return -1;
  130. }
  131.  
  132.  
  133.  
  134. SIOInit (char *whichport, char *speed, char *phone)
  135. {
  136.     char i;
  137.     SerShk    handshake;
  138.     int setting, baudCode, speedVal;
  139.     int err;
  140.     long int bytes;
  141.  
  142.     /*  fprintf( stderr, "sioinit %s %s\n", whichport, speed ); /* */
  143.     
  144.     if ( 
  145.         strncmp( whichport, ".a", 2 ) == 0 || 
  146.         strncmp( whichport, "a",1 ) == 0 ||
  147.         strcmp( whichport, "modem") == 0
  148.         ) 
  149.     {
  150.         curPort.in = AIN;
  151.         curPort.out = AOUT;
  152.     }
  153.     else if (
  154.         strncmp( whichport, ".b", 2 ) == 0 || 
  155.         strncmp( whichport, "b", 1 ) == 0 ||
  156.         strcmp( whichport, "printer") == 0 
  157.         ) 
  158.     {
  159.         curPort.in = BIN;
  160.         curPort.out = BOUT;
  161.     }
  162.     else if (strlen(whichport) == 1 && whichport[0] >= 'c' && whichport[0] <= 'z') {
  163.         otherIn[2] = otherOut[2] = whichport[0];
  164.         curPort.in = otherIn;
  165.         curPort.out = otherOut;
  166.     } else if (strlen(whichport) == 2 && whichport[0] == '.' && whichport[1] >= 'c' && whichport[1] <= 'z') {
  167.         otherIn[2] = otherOut[2] = whichport[1];
  168.         curPort.in = otherIn;
  169.         curPort.out = otherOut;
  170.     } else
  171.         return( -1 );
  172.  
  173.     baudCode = getbaud(speed);
  174.     if (baudCode == -1) {
  175.         fprintf(stderr, "Baud rate %s is not supported or not recognized\n", speed);
  176.         return (-1);
  177.     }
  178.     
  179.     speedVal = getspeed(baudCode);
  180.     
  181.     if (speedVal <= 9600) {
  182.         sleepLimit = 3;
  183.     } else if (speedVal < 57600) {
  184.         sleepLimit = 1;
  185.     } else {
  186.         sleepLimit = 0;
  187.     }
  188.  
  189.     if ((err = OpenDriver ( (StringPtr)curPort.in,  &curPort.refin )) !=0 ) {
  190.         fprintf( stderr, "Err: %d\n", err);
  191. #ifdef    DEBUG
  192.         debugMsg ( ctop( curPort.in ) );
  193. #endif
  194.         SysBeep (20); 
  195.         return( -1 );
  196.     }
  197.  
  198.     
  199.     if ((err=OpenDriver ( (StringPtr)curPort.out, &curPort.refout )) !=0 ) {
  200.         fprintf( stderr, "Err: %d\n", err);
  201. #ifdef    DEBUG
  202.         debugMsg ( ctop( curPort.out ) );
  203. #endif
  204.         SysBeep (20); 
  205.         return( -1 );
  206.     }
  207.     
  208.     SIOHandshake( FALSE, FALSE, FALSE, XON, XOFF );
  209.     SIOSetting( speed, noParity, stop10, data8 );
  210.  
  211. #ifdef DOASYNC
  212.  
  213.     bytes = BUFFERS * sizeof (struct async_write);
  214.  
  215.     asyncout = (struct async_write *) NewPtr(bytes);
  216.     if (asyncout) {
  217.         memset(asyncout, 0, bytes);
  218.     }
  219.     async_head = async_tail = 0;
  220.     allowInterrupts = interruptOccurred = FALSE;
  221.  
  222. #endif
  223.  
  224.     currentConnection = &serialHandler;
  225.  
  226.     return( 0 );
  227. }
  228.  
  229. SIOSpeed(char *speed)
  230. {
  231.     SIOSetting( speed, curPort.parity, curPort.stopbits, curPort.databits );
  232. }
  233.  
  234. SIOHandshake (int fInx, int fXOn, int fCTS, int xOn, int xOff)
  235. {    
  236.     int err;
  237.     
  238.     curPort.handshake.fInX = fInx;
  239.     curPort.handshake.fXOn = fXOn;
  240.     curPort.handshake.fCTS = fCTS;
  241.  
  242.     curPort.handshake.xOn = xOn;
  243.     curPort.handshake.xOff = xOff;
  244.     /* handshake.fXOn = TRUE; */
  245.     
  246.     curPort.handshake.errs = 0;
  247.     curPort.handshake.evts = 0;
  248.  
  249.     if ((err=SerHShake (curPort.refout, &curPort.handshake ))!=0 ) {
  250.         fprintf( stderr, "Err: %d\n", err);
  251. #ifdef    DEBUG
  252.         debugMsg ("\PSerHShake error");
  253. #endif
  254.         SysBeep (20); 
  255.     }
  256. }
  257.  
  258. SIOSetting(char *speed, int parity, int stopbits, int databits)
  259. {
  260.     int err;
  261.     int setting;
  262.     
  263.     curPort.baud = getbaud(speed);
  264.     curPort.parity = parity;
  265.     curPort.stopbits = stopbits;
  266.     curPort.databits = databits;
  267.     
  268.     setting = curPort.baud + parity + stopbits + databits;
  269. #ifdef Upgrade
  270.     /* store current settings in a global area */
  271.     g_setting = setting;
  272. #endif Upgrade
  273.  
  274.     if ((err=SerReset(curPort.refin, setting))!=0 ||
  275.         (err=SerReset(curPort.refout, setting))!=0)  {
  276.         fprintf( stderr, "Err: %d\n", err);
  277. #ifdef    DEBUG
  278.         debugMsg ("\PSerReset error");
  279. #endif
  280.         SysBeep (20);
  281.     }    
  282. }
  283.  
  284. SIOInBuffer (char *buf, int size)
  285. {
  286.     curPort.inbuffer = buf;
  287.     curPort.insize = size;
  288.     SerSetBuf( curPort.refin, buf, size ); 
  289. }
  290.  
  291. SIOOutBuffer (char *buf, int size)
  292. {
  293.     curPort.outbuffer = buf;
  294.     curPort.outsize = size;
  295.     SerSetBuf( curPort.refout, buf, size ); 
  296. }
  297.  
  298.  
  299. SIOClose (int dtr)
  300. {
  301.     CntrlParam SIOpb;
  302.     
  303.     long count;
  304.     int i;
  305.  
  306.     printmsg(2, "Closing serial port session");
  307.     if ( dtr != 0 && curPort.refin != 0) {
  308.         printmsg(2, "Dropping DTR");
  309.         /* drop DTR */
  310.         SIOpb.ioCompletion = NULL;
  311.         SIOpb.ioCRefNum = curPort.refin;
  312.         SIOpb.csCode = 18;
  313.         PBControl ((ParmBlkPtr)&SIOpb, FALSE);
  314.     }
  315.     
  316.     printmsg(2, "Setting input buffer to NULL");
  317.     SIOInBuffer( NULL, 0 );
  318.     printmsg(2, "Setting output buffer to NULL");
  319.     SIOOutBuffer( NULL, 0 );
  320.     if (curPort.refin != 0) {
  321.         printmsg(2, "Killing input port I/O");
  322.         KillIO(curPort.refin);
  323.         printmsg(2, "Closing input port");
  324.         CloseDriver( curPort.refin );
  325.     }
  326.     if (curPort.refout != 0) {
  327.         printmsg(2, "Killing output port I/O");
  328.         KillIO(curPort.refout);
  329.         printmsg(2, "Closing output port");
  330.         CloseDriver( curPort.refout );
  331.     }
  332.     if (asyncout) {
  333.         for (i = 0; i < BUFFERS; i++) {
  334.             if (asyncout[i].buf) {
  335.                 printmsg(2, "Disposing output buffer at 0x%lX", asyncout[i].buf);
  336.                 DisposPtr(asyncout[i].buf);
  337.             }
  338.         }
  339.         printmsg(2, "Disposing output control data at 0x%lX", asyncout);
  340.         DisposPtr(asyncout);
  341.         asyncout = NULL;
  342.     }
  343.     async_head = async_tail = async_pending = 0;
  344.     curPort.refin = curPort.refout = 0;
  345.     
  346.     currentConnection = (ConnectionHandler *) NULL;
  347.     printmsg(2, "Serial port teardown complete");
  348. }
  349.  
  350.  
  351. sfflushout (void)
  352. {
  353. }
  354.  
  355. SIOSetFlowCtl(int software, int hardware)
  356. {
  357.     SerShk flowRec;
  358.     flowRec.fXOn = software;
  359.     flowRec.fInX = software;
  360.     flowRec.fCTS = hardware;
  361.     flowRec.xOn =  0x11;
  362.     flowRec.xOff = 0x13;
  363.     flowRec.errs = flowRec.evts = 0;
  364. /*     SerHShake(curPort.refin, &flowRec); */
  365.     SerHShake(curPort.refout, &flowRec);
  366. }
  367.  
  368. SIOAllowInterrupts(int flag)
  369. {
  370.     int oldFlag;
  371.     oldFlag = allowInterrupts;
  372.     allowInterrupts = flag;
  373.     interruptOccurred &= flag;
  374.     return oldFlag;
  375. }
  376.  
  377. SIOInterrupt(void)
  378. {
  379.     interruptOccurred = TRUE;
  380. }
  381.  
  382. SIOPurge (void)
  383. {    /*
  384.     char        ch;
  385.  
  386.     while (sread (&ch, 1, 1) == 1);
  387.     
  388.     */
  389.     (void) KillIO(curPort.refin);
  390.     (void) KillIO(curPort.refout);
  391. }
  392.  
  393. SIOPutchar (char ch)
  394. {
  395.     /*fprintf(stderr, "<%02x>", ch);*/
  396.     return( putu ( &ch, 1, curPort.refout ) );    
  397. }
  398.  
  399. SIOWrite (char *buf, int count)
  400. {
  401.     return( putu (buf, count, curPort.refout) );
  402. }
  403.  
  404. int SIOAvail(void)
  405. {
  406.     long int count;
  407.     (void)SerGetBuf(curPort.refin, &count);
  408.     return count;
  409. }
  410.  
  411.  
  412. SIOWStr (char *st)
  413. {
  414.     return( putu (st, strlen(st), curPort.refout) );
  415. }
  416.  
  417. #define    Ticks            (*(long *)            0x16a)
  418.     
  419.  
  420. /* timeout is in tenths of a second */
  421. int SIORead (char *byt, int mincount, int maxcount, long int tenths)
  422. {
  423.     long    timea;
  424.     short    actCount;
  425.  
  426.     int        i;
  427.     
  428.     timea = Ticks;
  429.     tenths *= 6;
  430.     /* fprintf (stderr, "Read  m= %d T= %ld", maxcount, Ticks  );/**/
  431.     do {
  432.         actCount = getn (byt, mincount, maxcount, curPort.refin );
  433.  
  434.         if (actCount > 0) {
  435.             /* fprintf (stderr, "  OK: %d\n", actCount);/**/
  436.             return actCount;
  437.             }
  438.         
  439.         if (allowInterrupts && interruptOccurred) {
  440.             return -1;
  441.         }
  442.             
  443.     } while ((long)(Ticks - timea) < tenths);
  444.     
  445.     /* fprintf (stderr, "  Timed out: t= %d\n  T:%ld", tenths, Ticks );/**/
  446.     return -1;
  447.     }
  448.  
  449. srdchk (void)
  450. {
  451.     long count;
  452.  
  453.     (void)SerGetBuf(curPort.refin, &count);    
  454.     if (count >= 1) 
  455.         return TRUE;
  456.     else 
  457.         return FALSE;
  458. }
  459.  
  460. SIOBreak(int tenths) {
  461.     long int ticks;
  462.     ticks = TickCount();
  463.     SerSetBrk(curPort.refout);
  464.     while (TickCount() <= ticks+tenths*6) {
  465.         ;;;;;;;;
  466.     }
  467.     SerClrBrk(curPort.refout);
  468. }
  469.  
  470. SIOSetParity(int dataBitsCode, int parityCode) {
  471.     int setting;
  472.     OSErr err;
  473.     setting = (g_setting & 0xC3FF) | parityCode | dataBitsCode;
  474.     if ((err=SerReset(curPort.refin, setting))!=0  ||
  475.         (err=SerReset(curPort.refout, setting))!=0)  {
  476.         fprintf( stderr, "Err: %d\n", err);
  477. #ifdef    DEBUG
  478.         debugMsg ("\PSerReset error");
  479. #endif
  480.         SysBeep (20);
  481.     } else {
  482.         g_setting = setting;
  483.     }
  484. }
  485.  
  486. /*     Fill array *cp with characters from serial buffer, starting
  487.     at 0, until cmax. Return actual chars read. Don't read unless
  488.     at least cmin are available.
  489. */
  490. int getn (char *cp, int cmin, int cmax, short refin)
  491. {    
  492.     ParamBlockRec    SIOpb;
  493.     register        ParmBlkPtr    pbp = &SIOpb;
  494.  
  495.     long            count;
  496.     int                firstTry = TRUE;
  497.  
  498.     /* fprintf( stderr, " %d", cmin ); /* */
  499.     
  500. tryit:
  501.     (void)SerGetBuf(refin, &count);
  502.     SIOpb.ioParam.ioReqCount = count;
  503.     if ( count >= cmin) {
  504.         if ( count >  cmax) 
  505.             SIOpb.ioParam.ioReqCount = (long) cmax;
  506.            SIOpb.ioParam.ioRefNum = refin;
  507.            SIOpb.ioParam.ioBuffer = (Ptr) cp;
  508.            SIOpb.ioParam.ioPosMode = 0;
  509.         PBRead (&SIOpb, FALSE);
  510.         count = SIOpb.ioParam.ioActCount;
  511. #ifdef MULTIFINDER
  512.         if (Ticks-Last_Check_Event >= MF_DELAY)  
  513.           if (Check_Events(0)) {
  514.             if (Main_State == Abort_Program) {
  515.                 SIOClose(TRUE);
  516.                 exit(-1);
  517.             }
  518.           }
  519. #endif 
  520.         }
  521.     else {
  522. #ifdef MULTIFINDER
  523.         /* the data hasn't been received, ok to delay a bit */
  524.         if (Ticks-Last_Check_Event >= MF_DELAY)  
  525.           if (Check_Events(sleepLimit)) {
  526.             if (Main_State == Abort_Program)  {
  527.                 SIOClose(TRUE);
  528.                 exit(-1);
  529.             }
  530.            }
  531. #endif 
  532.         count = 0;
  533.         if (firstTry) {
  534.             firstTry = FALSE;
  535.             goto tryit;
  536.         }
  537.     }
  538.         
  539.  
  540.     return( (int)count );
  541. }
  542.  
  543.  
  544. static ParamBlockRec          pb = {0};
  545.  
  546. int SIOWriteBusy(void)
  547. {
  548.     if (pb.ioParam.ioResult == 1) {
  549.         return TRUE;
  550.     } else {
  551.         return FALSE;
  552.     }
  553. }
  554.     
  555.  
  556. int putu(char *c, short count, short refout)
  557. {
  558.     register ParmBlkPtr    pbp = &pb;
  559.     int spin;
  560.     int isAsync;
  561.  
  562. #ifdef DOASYNC
  563.     if (asyncout != NULL) {
  564.         spin = TRUE;
  565.         do {
  566.             if (async_pending == 0) {
  567.                 spin = FALSE;
  568.             } else {
  569.                 pbp = &asyncout[async_tail].pb;
  570.                 if (pbp->ioParam.ioResult != 1) {
  571.                     async_pending --;
  572.                     async_tail = (async_tail + 1) % BUFFERS;
  573.                 } else {            
  574. #ifdef MULTIFINDER
  575.                     if (Ticks-Last_Check_Event >= MF_DELAY) 
  576.                       if (Check_Events(0)) 
  577.                         if (Main_State == Abort_Program)  {
  578.                               SIOClose(TRUE);
  579.                             exit(-1);
  580.                         }
  581. #endif
  582.                     if (async_pending < BUFFERS) {
  583.                         spin = FALSE;
  584.                     }
  585.                 }
  586.             }
  587.         } while (spin);
  588.         
  589.         pbp = &asyncout[async_head].pb;
  590.         
  591.         if (asyncout[async_head].bufSize < count) {
  592.             if (asyncout[async_head].bufSize > 0) {
  593.                 DisposPtr(asyncout[async_head].buf);
  594.                 asyncout[async_head].buf = NULL;
  595.                 asyncout[async_head].bufSize = 0;
  596.             }
  597.             asyncout[async_head].buf = NewPtr(count);
  598.             if (asyncout[async_head].buf == NULL) {
  599.                 goto writeSync;
  600.             }
  601.             asyncout[async_head].bufSize = count;
  602.         }
  603.                 
  604.         memcpy(asyncout[async_head].buf, c, (long) count);
  605.         
  606.         pbp->ioParam.ioCompletion = NULL;
  607.         pbp->ioParam.ioRefNum = refout;
  608.         pbp->ioParam.ioBuffer = asyncout[async_head].buf;
  609.         pbp->ioParam.ioReqCount = count;
  610.         pbp->ioParam.ioPosMode = 0;
  611.         
  612.         PBWrite(pbp, TRUE);
  613.  
  614.         async_head = (async_head + 1) % BUFFERS;
  615.         async_pending ++;
  616.     } else {
  617. #endif
  618. writeSync:
  619.         pb.ioParam.ioCompletion = NULL;
  620.         pb.ioParam.ioRefNum = refout;
  621.         pb.ioParam.ioBuffer = c;
  622.         pb.ioParam.ioReqCount = count;
  623.         pb.ioParam.ioPosMode = 0;
  624.       
  625.         PBWrite(&pb, FALSE );
  626. #ifdef DOASYNC
  627.     }
  628. #endif
  629.     
  630. #ifdef MULTIFINDER
  631.         if (Ticks-Last_Check_Event >= MF_DELAY) 
  632.           if (Check_Events(0)) 
  633.             if (Main_State == Abort_Program)  {
  634.                   SIOClose(TRUE);
  635.                 exit(-1);
  636.             }
  637. #endif 
  638.  
  639.     return( (short) pb.ioParam.ioActCount );
  640. }
  641.  
  642. SIOIdle()
  643. {
  644. }
  645.  
  646. int SIOEvent(EventRecord *anEvent)
  647. {
  648.     return 0;
  649. }
  650.  
  651.